/*
 * @Descripttion: 
 * @Author: yubo
 * @Date: 2022-11-04 15:36:25
 * @LastEditTime: 2022-11-07 17:16:16
 */
/// impl Trait 语法
/// 

use std::fmt::Debug;

pub trait Fly {
    fn fly(&self) -> bool;
}

#[derive(Debug)]
struct Duck;

#[derive(Debug)]
struct Pig;

impl Fly for Duck {
    fn fly(&self) -> bool {
        return true;
    }
}

impl Fly for Pig {
    fn fly(&self) -> bool {
        return false;
    }
}

//
fn fly_static(s: impl Fly + Debug) -> bool {
    s.fly()
}

//将impl Trait语法用于返回值位置的时候，实际上等价于给返回类型增加一种trait限定范围
fn can_fly(s: impl Fly + Debug) -> impl Fly {
    if s.fly() {
        println!("{:?} can fly", s);
    }else {
        println!("{:?} can't fly", s);
    }
    s
}

//返回trait对象
fn dyn_can_fly(s: impl Fly+Debug+'static) -> Box<dyn Fly> {
    if s.fly() {
        println!("{:?} can fly", s);
    }else {
        println!("{:?} can't fly", s);
    }
    Box::new(s)
}

fn main() {
    let pig = Pig;
    assert_eq!(fly_static(pig), false);
    let duck = Duck;
    assert_eq!(fly_static(duck), true);

    let pig = Pig;
    let pig = can_fly(pig);
    
    let duck = Duck;
    let duck = can_fly(duck);
}
